import json
import time
from collections import OrderedDict
from util.mysql_utils import *
from binance.um_futures import UMFutures
from binance.websocket.um_futures.websocket_client import UMFuturesWebsocketClient

from util.UTILS import *

class StrategyAngel:

    def __init__(self):
        key = "lSfS73A8jxifi2btCmE7fPnhrg5Zf333pyGZkuuwHvZ7GrZg11gyE52SrfY0Kmms"
        secret = "8CUn0fvnmJ7ufDZ0BuVuMzu2jOkOb9vfQ077p3iQTyL6IL6WquQa3AgQ8BIW1cAS"
        self.kline_store= {}
        self.um_futures_client = UMFutures(key=key, secret=secret)
        self.um_futures_websockt_client = UMFuturesWebsocketClient(on_message=self.message_handler)
        #订阅  k线 间隔  根据 需求u同 调整
        self.interval = '1m'
        # key  ： symbol    val : 存储  上次计算连续 k线的位置
        self.symbol_kline_data_positions = {}
        self.trading_condition = 0.005
        self.subscribe_coin()


    def cal_segment(self):
        #计算所有币对 是否有连续 线段
        #要保证不重复 计算  计算完成后需要记录位置 如何包装 不重复 计算 需要有一个机制
        # 保证不重复计算的 方案：发现完一段 数据 则丢弃 上一段 数据
        #存储 kline data  到 有序集合  然后 程序不断 扫描 有序集合
        for symbol in self.kline_store:
            kline_order_dict = self.kline_store[symbol]
            previous_kline = None
            fall_segment = []
            for key in kline_order_dict:
                kline_data = kline_order_dict[key]
                print('symbol {}   segment size {}'.format(symbol,len(fall_segment)))
                if previous_kline:
                    # key = c 为 close 价格
                    previous_kline_close_price = float(previous_kline['c'])
                    curr_kline_close_price = float(kline_data['c'])
                    #当前kline 的涨跌幅度
                    pc_up_p = abs(float(kline_data['o'])/float(kline_data['c'])-1)
                    #计算连续 下跌 如果  前一个kline 的close 大于当前的 close  说明下跌
                    if previous_kline_close_price <= curr_kline_close_price:
                        fall_segment.append(kline_data)
                    else:
                        # 判断 涨跌幅 是否 大于 0.006 如果小于 则不认为 连续线段被打破
                        if pc_up_p >= 0.0006:
                            if len(fall_segment) >= 2:
                                # 下跌幅度  第一根k线的open  / 最后一根k线的 close
                                segment_change_p = abs(float(fall_segment[0]['c'])/float(fall_segment[len(fall_segment)-1]['c']) - 1)
                                print('symbole {}   p {}'.format(symbol,segment_change_p))
                                if segment_change_p >= self.trading_condition:
                                    #调用交易 启动交易 程序  以及删除 这一段 数据
                                    self.clean_kline_date(symbol)
                                    print('**************开始时间 : {}  结束时间: {} 涨跌幅 : {} '.format(millisecond_2_date_str(fall_segment[0]['t']),millisecond_2_date_str(fall_segment[len(fall_segment)-1]['t']),segment_change_p))
                            #如果  pc_up_p >= 0.006:  说明 变化 幅度 太小  可以认为 连续性 没有改变
                            #连续 k线 阻断 集合
                            fall_segment = []
                        else:
                            fall_segment.append(kline_data)


                    previous_kline = kline_data

                else:
                    previous_kline = kline_data

    def clean_kline_date(self,symbol):
        self.kline_store[symbol] = OrderedDict()

    def message_handler(self,_, message):

        obj = json.loads(message)

        if 's' in obj:
            # print(obj['e'])
            # k线 时间
            kline_start_time = obj['E']
            #币对 名称
            symbol = obj['s']
            # if symbol != 'ETHUSDT':
            #     return
            #k线数据
            kline_data = obj['k']
            if symbol not in self.kline_store:
            #创建 有序集合
                self.kline_store[symbol] = OrderedDict()

            if kline_data['x']:
                if kline_start_time not in self.kline_store[symbol].keys():
                    self.kline_store[symbol][kline_start_time] = kline_data


    def subscribe_coin(self):
        all_symbol = self.get_all_symbole()
        for symbole in all_symbol:
            # if symbole == 'ETHUSDT':
            self.um_futures_websockt_client.kline(
                symbol=symbole,
                # id=12,
                interval=self.interval
            )
            time.sleep(0.2)

    def get_all_symbole(self):
        symbol_list = self.um_futures_client.exchange_info()
        result = []
        for _symbol in symbol_list['symbols']:
            result.append(_symbol['symbol'])
        return result




if __name__ == '__main__':
    sa = StrategyAngel()

    while True:
        # for symbol in sa.kline_store:
        #     print('-------------------------')
        #     for time_key in sa.kline_store[symbol].keys():
        #         print(millisecond_2_date_str(time_key))
        #     print('-------------------------')
        #     time.sleep(20)
        # time.sleep(11)
        try:
            sa.cal_segment()
            time.sleep(10)
        except Exception as e:
            print(e)
    # 测试
    # 流程
